#pragma once
#include <cuda_runtime.h>

#include <cstdio>
#include <stdexcept>
#include <string>
#include <vector>

#include "logger.h"

// CUDA 检查错误的宏
#define MYCHECK(call)                                                                                             \
    {                                                                                                             \
        cudaError_t error = call;                                                                                 \
        if (error != cudaSuccess)                                                                                 \
        {                                                                                                         \
            fprintf(stderr, "CUDA error: %s file: %s line: %d\n", cudaGetErrorString(error), __FILE__, __LINE__); \
            throw std::runtime_error("CUDA operation failed");                                                    \
        }                                                                                                         \
    }

// 测试基类
class CudaTest
{
public:
    virtual ~CudaTest() = default;
    virtual void run() = 0;
    virtual std::string name() const = 0;
};

// 测试管理器
class CudaTestManager
{
public:
    static CudaTestManager& getInstance()
    {
        static CudaTestManager instance;
        return instance;
    }

    void registerTest(CudaTest* test) { _tests.push_back(test); }

    void runAllTests()
    {
        MYINFO("Starting all CUDA tests...");
        int passed = 0;

        for (auto test : _tests)
        {
            try
            {
                MYINFO("\nRunning test: {0}", test->name());
                test->run();
                MYINFO("Test passed: {0}", test->name());
                passed++;
            }
            catch (const std::exception& e)
            {
                MYERROR("Test failed: {0}", test->name());
                MYERROR("Error message: {0}", e.what());
            }
        }

        MYINFO("\nTest results: {0}/{1} passed", passed, _tests.size());
    }

private:
    CudaTestManager() = default;
    std::vector<CudaTest*> _tests;
};

// 测试注册器
#define REGISTER_TEST(TestClass)                                                                 \
    class TestClass##Registrar                                                                   \
    {                                                                                            \
    public:                                                                                      \
        TestClass##Registrar() { CudaTestManager::getInstance().registerTest(new TestClass()); } \
    };                                                                                           \
    static TestClass##Registrar g_##TestClass##Registrar;
